//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package dataview_dao

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao/db_ns"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_dataview_api"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
)

type NodeInfoDbItem struct {
	NodeId   string `bson:"_id"`
	ViewId   string `bson:"viewId"`
	NodeType uint32 `bson:"nodeType"`
	X        int32  `bson:"x"`
	Y        int32  `bson:"y"`
	W        uint32 `bson:"w"`
	H        uint32 `bson:"h"`
	BgColor  string `bson:"bgColor"`

	//节点数据
	RefTargetId   string `bson:"refTargetId"`
	BaseGroupName string `bson:"baseGroupName"`
	BaseText      string `bson:"baseText"`
	BaseIframeUrl string `bson:"baseIframeUrl"`
}

func (item *NodeInfoDbItem) ToNodeInfo() *project_dataview_api.NodeInfo {
	retObj := &project_dataview_api.NodeInfo{
		NodeId:   item.NodeId,
		NodeType: project_dataview_api.NODE_TYPE(item.NodeType),
		X:        item.X,
		Y:        item.Y,
		W:        item.W,
		H:        item.H,
		BgColor:  item.BgColor,
	}
	if item.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_GROUP) {
		retObj.NodeData = &project_dataview_api.NodeInfo_BaseGroupName{
			BaseGroupName: item.BaseGroupName,
		}
	} else if item.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_TEXT) {
		retObj.NodeData = &project_dataview_api.NodeInfo_BaseText{
			BaseText: item.BaseText,
		}
	} else if item.NodeType == uint32(project_dataview_api.NODE_TYPE_NODE_TYPE_BASE_IFRAME) {

		retObj.NodeData = &project_dataview_api.NodeInfo_BaseIframeUrl{
			BaseIframeUrl: item.BaseIframeUrl,
		}
	} else {
		retObj.NodeData = &project_dataview_api.NodeInfo_RefTargetId{
			RefTargetId: item.RefTargetId,
		}
	}

	return retObj
}

type _NodeDao struct {
	mc *mongo.Collection
}

func newNodeDao(db *mongo.Database) (*_NodeDao, error) {
	mc := db.Collection(db_ns.DB_NS_PROJECT_DATAVIEW + "node")
	_, err := mc.Indexes().CreateOne(context.Background(), mongo.IndexModel{
		Keys: bson.D{{"viewId", 1}},
	})
	if err != nil {
		return nil, err
	}
	return &_NodeDao{mc: mc}, nil
}

func (db *_NodeDao) Insert(ctx context.Context, dbItem *NodeInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_NodeDao) Exist(ctx context.Context, viewId, nodeId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"viewId": viewId, "_id": nodeId})
	return count > 0, err
}

func (db *_NodeDao) Get(ctx context.Context, viewId, nodeId string) (*NodeInfoDbItem, error) {
	retItem := &NodeInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}).Decode(retItem)
	return retItem, err
}

func (db *_NodeDao) Remove(ctx context.Context, viewId, nodeId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"viewId": viewId, "_id": nodeId})
	return err
}

func (db *_NodeDao) RemoveByView(ctx context.Context, viewId string) error {
	_, err := db.mc.DeleteMany(ctx, bson.M{"viewId": viewId})
	return err
}

func (db *_NodeDao) List(ctx context.Context, viewId string) ([]*NodeInfoDbItem, error) {
	cursor, err := db.mc.Find(ctx, bson.M{"viewId": viewId})
	if err != nil {
		return nil, err
	}

	retList := []*NodeInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_NodeDao) UpdatePosition(ctx context.Context, viewId, nodeId string, x, y int32) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"x": x,
			"y": y,
		},
	})
	return err
}

func (db *_NodeDao) UpdateSize(ctx context.Context, viewId, nodeId string, w, h uint32) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"w": w,
			"h": h,
		},
	})
	return err
}

func (db *_NodeDao) UpdateBgColor(ctx context.Context, viewId, nodeId, bgColor string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"bgColor": bgColor,
		},
	})
	return err
}

func (db *_NodeDao) UpdateBaseGroupName(ctx context.Context, viewId, nodeId string, value string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"baseGroupName": value,
		},
	})
	return err
}

func (db *_NodeDao) UpdateBaseText(ctx context.Context, viewId, nodeId string, value string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"baseText": value,
		},
	})
	return err
}

func (db *_NodeDao) UpdateBaseIframeUrl(ctx context.Context, viewId, nodeId string, value string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"baseIframeUrl": value,
		},
	})
	return err
}

func (db *_NodeDao) UpdateRefTarget(ctx context.Context, viewId, nodeId string, nodeType uint32, refTargetId string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"viewId": viewId, "_id": nodeId}, bson.M{
		"$set": bson.M{
			"nodeType":    nodeType,
			"refTargetId": refTargetId,
		},
	})
	return err
}
